title: CustomShape: Animated Path Outlines description: Documents CustomShape with an animatable numeric value and a synchronous path(value, rect) builder returning Path2D, including animation usage, fill/stroke/trim support and a morphing example.
Path2D is a vector path you build segment by segment, mirroring SwiftUI's Path. It is a
plain value: build it with line and curve commands, query its geometry, transform it, render it
with the <PathShape> view, or use it as a clipping / hit-testing / container shape.
The name
Path2Dis used becausePathis already taken by the file-path utilities. The drawing API itself follows SwiftUI'sPath.
Conventions
- Points are
{ x, y }, rectangles are{ x, y, width, height }. - Angles are in radians.
- Build methods are chainable (they return the path).
- Coordinates are absolute (in the shape's own coordinate space), exactly like SwiftUI's
Path.
Building a path
Build methods
clockwisefollows SwiftUI's convention. This is the opposite of the Web Canvascounterclockwiseflag — keep that in mind when porting Canvas code.
Rendering with <PathShape>
<PathShape> renders a Path2D as a SwiftUI shape. It accepts fill, stroke, trim and all
view modifiers, exactly like Rectangle or Circle. Provide either path (a prebuilt value)
or draw (a size-responsive builder, like <Canvas>).
Sizing is controlled by view modifiers (frame, padding, ...). With draw, the actual draw size
is the second argument; do not call setState inside the closure.
Geometry queries
These are computed on demand and return immediately.
Transforming
Transforms return a new Path2D (the original is unchanged).
As a clip / content / container shape
Pass a Path2D anywhere a shape is accepted:
To use a path as a mask, render it as a <PathShape> and pass that view to mask:
CustomShape: animate a custom outline
CustomShape is a native SwiftUI shape with one animatable numeric value.
Its synchronous path(value, rect) builder returns a Path2D. SwiftUI interpolates the value and
passes the current presentation value plus { x, y, width, height } to each path evaluation.
It supports the same fill, stroke, trim, and view modifiers as PathShape.
You can also update value inside withAnimation. Without an animation transaction it jumps to the target.
Use the builder's first argument, not a captured target state, to compute the path.
The builder may run multiple times per frame. Return a Path2D synchronously and avoid state changes,
network requests, and other side effects. Errors or invalid returns log an error and render an empty path.
The target value must be finite; spring animations may overshoot their endpoints.
Each evaluation still calls JS and parses path commands, so measure complex paths on device.
System-rendered widget snapshots do not guarantee continuous animation.
This API interpolates one number; it does not automatically match arbitrary path vertices or animate static Path2D clip shapes.
